<template>
  <!-- <div class="scene-tree-wrapper" @dragenter="dragEnter($event)" @dragleave="dragLeave($event)"
    @dragover="dragOver($event)" @drop="dropFile($event)"> -->
  <div class="scene-tree-wrapper">
    <!-- <Expand :dragEnableX="false" :showResize="isShowTree"> -->
    <TreeComp :tree="(sceneTree as unknown as Tree<TreeItem>)" @click="sceneTree.sceneUiTree.clearAllSelectedItems()"
      @blur="sceneTree.sceneUiTree.clearAllSelectedItems()" @contextmenu.stop.prevent=contexMenuEvent(undefined)>
      <template v-slot:default="slotProps">
        <SceneTreeItemComp :sceneTreeItem="(slotProps.treeItem as unknown as SceneTreeItem)" :key="slotProps.key"
          @contexMenuEvent="(sceneUiTreeObject: SceneTreeItem | undefined) => contexMenuEvent(sceneUiTreeObject)"
          :isLastSelectedObject="(slotProps.treeItem as unknown as SceneTreeItem) === sceneTree.lastSelectedItem"
          :tree="sceneTree" :showCheckBox="showCheckBox">
        </SceneTreeItemComp>
      </template>
    </TreeComp>
    <ContextMenuCom :baseItems="menuContent"></ContextMenuCom>
    <!-- </Expand> -->
  </div>
  <ImagesCzm :sceneObject="popTreeItem" v-if="popTreeItem" @close="popTreeItem = undefined"></ImagesCzm>
  <DraggablePopup2 :title="'属性管理器'" :left="'calc(100% - 400px)'" v-if="propIsShow" @close="close" :width="400"
    :top="'calc(100% - 630px)'" :height="'600px'">
    <PropTreeWrapper v-if="propIsShow" :nameTitle="'属性管理器'" :propTree="propTreeRef" :key="propTreeKey">
    </PropTreeWrapper>
  </DraggablePopup2>
</template>

<script setup lang="ts">
import { Message, messageBox } from "earthsdk-ui";
import { ES3DTileset, ESGeoJson, ESImageryLayer, ESTerrainLayer } from 'esobjs-xe2-plugin/dist-node/esobjs-xe2-plugin-main';
import { Ref, inject, onBeforeUnmount, onMounted, ref } from "vue";
import { createVueDisposer, toReadonlyVueRef, toRefKey } from "vue-xe2-plugin/dist-node/components/xe2/tools";
import { PropTree, SceneTree, SceneTreeItem } from "xbsj-xe2/dist-node/xe2";
import { FileHandleType, getSaveFileHandle, saveFile } from "xbsj-xe2/dist-node/xe2-base-objects";
import { saveFileHandle, save } from "./tools"
import { JsonValue } from "xbsj-xe2/dist-node/xe2-base-utils";
import { Tree, TreeItem, TreeItemInsertFlag } from 'xbsj-xe2/dist-node/xe2-utils';
import { getNoToken } from "../../api/service";
import { XbsjEarthUi } from "../../scripts/xbsjEarthUi";
import DraggablePopup2 from '../DraggablePopup2.vue';
import ImagesCzm from "../cesiumView/ImagesCzm.vue";
import ContextMenuCom from "../commom/ContextMenuCom.vue";
import TreeComp from "../commom/Tree.vue";
import PropTreeWrapper from "../propTree/PropTreeWrapper.vue";
import SceneTreeItemComp from "./SceneTreeItem.vue";
import { createLines, createpoints, createpolygons, geojsonToPointsLinesPolygons, searchForLineValues } from "./tools";
const topojson = require('topojson-client');

withDefaults(defineProps<{
  showCheckBox: boolean
}>(), {
  showCheckBox: false
});
const xbsjEarthUi = inject('xbsjEarthUi') as XbsjEarthUi
const sceneTree = inject('sceneTree') as SceneTree
const propIsShow = ref(false)
const disposer = createVueDisposer(onBeforeUnmount);
const { propUiTreeManager } = xbsjEarthUi;
const propTreeRef = toReadonlyVueRef(disposer, [propUiTreeManager, 'propTree']) as Ref<PropTree>;
const propTreeKey = toRefKey(propTreeRef);
const close = () => {
  propIsShow.value = false
  xbsjEarthUi.propUiTreeManager.sceneObject = undefined;
}

const popTreeItem = ref()
type menuContentType = {
  text: string;
  keys: string;
  func: () => void;
} | {
  type: "divider",
}
const deletetreeItem = ref()
const deleteFlag = ref(false)
const openCreator = (event: KeyboardEvent) => {
  if (!(event.ctrlKey && event.key === '`')) return
}

const confirm = () => {
  deleteselect(deletetreeItem.value)
  if (xbsjEarthUi.propSceneTree && xbsjEarthUi.propSceneTree.isDestroyed()) {
    xbsjEarthUi.propSceneTree = undefined
  }
  propIsShow.value = false
  xbsjEarthUi.propUiTreeManager.sceneObject = undefined;
  Message.success('删除成功')
}
//删除
const deleteselect = (treeItem: SceneTreeItem) => {
  if (deleteFlag.value) {
    deleteFlag.value = false
    const list = [...sceneTree.selectedItems] //删除选中
    list.forEach(obj => {
      if (obj.isDestroyed()) return
      obj.detachFromParent()
    })
  } else if (treeItem) {
    const list = [...sceneTree.selectedItems] //删除选中
    list.forEach(obj => {
      if (obj.isDestroyed()) return
      obj.detachFromParent()
    })
    const flag = treeItem.isDestroyed()
    if (flag) return
    treeItem.detachFromParent()
  }


}
onMounted(() => {
  window.addEventListener('keydown', openCreator)
  window.addEventListener('keydown', deleteItem)
  onBeforeUnmount(() => {
    window.removeEventListener('keydown', openCreator)
    window.removeEventListener('keydown', deleteItem)
  })
})
//添加文件夹
const addNewTreeItem = (treeItem: SceneTreeItem | undefined, location?: TreeItemInsertFlag | undefined) => {
  const groupscenetreeitem = sceneTree.createGroupTreeItem(undefined, undefined, treeItem, location)
  if (!groupscenetreeitem) return
  groupscenetreeitem.name = '新建文件夹';
}

const saveAs = async (json: JsonValue, name?: string) => {
  try {
    let handle: FileHandleType | undefined
    Message.warning('正在另存为..');
    if (name === undefined) {
      handle = await getSaveFileHandle('json', name);
    } else if (name === 'scene') {
      handle = await getSaveFileHandle('json', name);
    } else {
      handle = await getSaveFileHandle('json', `${name}.sceneObject`);
    }
    // handle = await getSaveFileHandle('json', `${name}.sceneObject`);
    if (!handle) return;
    const jsonStr = JSON.stringify(json, undefined, '    ');
    await saveFile(handle, jsonStr);
    Message.success('另存成功!');
  } catch (error) {
    Message.error(`另存失败! error: ${error}`);
  }
}
let checkedItems: any
let fatherItem: any
const whiteSpaceContexMenuEvent = () => {//空白右键
  const baseItems: Array<menuContentType> = [
    {
      text: "添加文件夹",
      keys: "",
      func: () => {
        addNewTreeItem(undefined)
      },
    },
    {
      text: "下载场景配置",
      keys: "",
      func: () => {
        const json = xbsjEarthUi.json;
        const name = 'scene'
        console.log(json);
        saveAs(json, name);
      },
    }, {
      text: "导出为Geojson文件",
      keys: "",
      func: async () => {
        const a = searchForLineValues(xbsjEarthUi, xbsjEarthUi.sceneTree.json.root)
        try {
          Message.warning('正在另存为..');
          const handle = await saveFileHandle('geoJson', 'geoJson场景对象');
          if (!handle) return;
          const jsonStr = JSON.stringify(a, undefined, '    ');
          await save(handle, jsonStr);
          Message.success('另存成功!');
        } catch (error) {
          Message.error(`另存失败! error: ${error}`);
        }
      },
    },
  ];
  menuContent.value = baseItems
}
const saveParms = async (treeItem: SceneTreeItem) => {
  const { sceneObject } = treeItem
  let position: [number, number, number];
  let rotation: [number, number, number];
  const res = await xbsjEarthUi.activeViewer?.getCurrentCameraInfo()
  if (!res) {
    Message.warning('无法获取视角')
    return
  }
  position = res.position
  rotation = res.rotation
  //@ts-ignore
  sceneObject.flyInParam = { position, rotation, flyDuration: 1 }
  // console.log(sceneObject);
}
const treeItemContexMenuEvent = (treeItem: SceneTreeItem) => {//文件夹右键
  const baseItems: Array<menuContentType> = [
    {
      text: "添加同级文件夹",
      keys: "",
      func: () => {
        addNewTreeItem(treeItem, 'After');
      },
    },
    {
      text: "添加内部文件夹",
      keys: "",
      func: () => {
        addNewTreeItem(treeItem, 'Inner');
      },
    },
    {
      type: "divider",
    },
    {
      text: "导出为Geojson文件",
      keys: "",
      func: async () => {
        const a = searchForLineValues(xbsjEarthUi, treeItem.json)
        try {
          Message.warning('正在另存为..');
          const handle = await saveFileHandle('geoJson', 'geoJson场景对象');
          if (!handle) return;
          const jsonStr = JSON.stringify(a, undefined, '    ');
          await save(handle, jsonStr);
          Message.success('另存成功!');
        } catch (error) {
          Message.error(`另存失败! error: ${error}`);
        }
      },
    },
    {
      text: "克隆",
      keys: "",
      func: () => {
        if (!treeItem.parent) {
          console.warn(`父节点不存在，无法克隆！`);
          return;
        }
        if (!treeItem.parent.children) {
          console.error(`父节点的children属性必须存在，否则当前节点从哪里来？treeItem.parent.children`);
          return;
        }
        const cloneTreeItem = treeItem.clone();
        if (!cloneTreeItem) {
          console.warn(`节点克隆失败！`);
          return;
        }
        treeItem.parent.children.push(cloneTreeItem);
      },
    },
    {
      text: "剪切",
      keys: "",
      func: () => {
        checkedItems = [...sceneTree.selectedItems]
        if (!checkedItems.includes(treeItem)) {
          checkedItems.push(treeItem)
        }
      },
    },
    {
      text: "删除",
      keys: "",
      func: () => {
        deletetreeItem.value = treeItem
        messageBox({ text: '确认删除图层?' })
          .then(() => {
            confirm()
          })
          .catch((err) => {
          })
      },
    },
    {
      type: "divider",
    },
    {
      text: "重命名",
      keys: "",
      func: () => {
        treeItem.nameEditing = true
      },
    },
    {
      text: "打印配置",
      keys: "",
      func: () => {
        // const jsonStr = treeItem.sceneObject?.jsonStr;
        const jsonStr = treeItem?.jsonStr;
        if (jsonStr) {
          console.log(jsonStr);
        }
      },
    },
    {
      text: "下载配置",
      keys: "",
      func: () => {
        const json = treeItem?.json;
        const name = treeItem?.name
        saveAs(json, name);
      },
    },

  ]
  const pasteList: Array<menuContentType> = [
    {
      text: "粘贴到节点下方",
      keys: "",
      func: () => {
        fatherItem = treeItem
        if (Tree.canMoveToTreeItems(checkedItems, fatherItem, 'after')) {
          Tree.moveToTreeItems(checkedItems, fatherItem, 'after')
          checkedItems = null
        }
      },
    },
    {
      text: "粘贴到节点上方",
      keys: "",
      func: () => {
        fatherItem = treeItem
        if (Tree.canMoveToTreeItems(checkedItems, fatherItem, 'before')) {
          Tree.moveToTreeItems(checkedItems, fatherItem, 'before')
          checkedItems = null
        }
      },
    },
    {
      text: "粘贴到节点内部",
      keys: "",
      func: () => {
        fatherItem = treeItem
        if (Tree.canMoveToTreeItems(checkedItems, fatherItem, 'inner')) {
          Tree.moveToTreeItems(checkedItems, fatherItem, 'inner')
          checkedItems = null
        }
      },
    },
  ]
  if (checkedItems) {
    pasteList.forEach((item) => {
      baseItems.splice(5, 0, item)
    })
  }
  menuContent.value = baseItems
}
const imageContexMenuEvent = (treeItem: SceneTreeItem) => {//节点右键
  const baseItems: Array<menuContentType> = [
    {
      text: "定位",
      keys: "",
      func: () => {
        flyTo(treeItem);
      },
    },
    // {
    //   text: "保存观察视角",
    //   keys: "",
    //   func: () => {
    //     saveParms(treeItem)
    //   },
    // },
    {
      type: "divider",
    },
    // {
    //   text: "剪切",
    //   keys: "",
    //   func: () => {
    //     checkedItems = [...sceneTree.selectedItems]
    //     if (!checkedItems.includes(treeItem)) {
    //       checkedItems.push(treeItem)
    //     }
    //   },
    // },
    // {
    //   text: "克隆",
    //   keys: "",
    //   func: () => {
    //     if (!treeItem.parent) {
    //       console.warn(`父节点不存在，无法克隆！`);
    //       return;
    //     }

    //     if (!treeItem.parent.children) {
    //       console.error(`父节点的children属性必须存在，否则当前节点从哪里来？treeItem.parent.children`);
    //       return;
    //     }
    //     const cloneTreeItem = treeItem.clone();
    //     if (!cloneTreeItem) {
    //       console.warn(`节点克隆失败！`);
    //       return;
    //     }
    //     treeItem.parent.children.push(cloneTreeItem);
    //   },
    // },
    {
      text: "删除",
      keys: "",
      func: () => {
        deletetreeItem.value = treeItem
        messageBox({ text: '确认删除图层?' })
          .then(() => {
            confirm()
          })
          .catch((err) => {
          })
      },
    },
    // {
    //   type: "divider",
    // },
    {
      text: "重命名",
      keys: "",
      func: () => {
        treeItem.nameEditing = true
      },
    },
    // {
    //   text: "打印配置",
    //   keys: "",
    //   func: () => {
    //     const jsonStr = treeItem.sceneObject?.jsonStr;
    //     if (jsonStr) {
    //       console.log(jsonStr);
    //     }
    //   },
    // },
    // {
    //   text: "下载配置",
    //   keys: "",
    //   func: () => {
    //     const json = treeItem.sceneObject?.json;
    //     const name = treeItem.sceneObject?.name
    //     saveAs(json, name);
    //   },
    // },
    // {
    //   type: "divider",
    // },

    {
      text: "属性",
      keys: "",
      func: () => {
        xbsjEarthUi.propSceneTree = treeItem
      },
    }
    // {
    //   text: "完整属性",
    //   keys: "",
    //   func: () => {
    //     propIsShow.value = true
    //     xbsjEarthUi.propUiTreeManager.sceneObject = treeItem.sceneObject;
    //   },
    // }
  ]
  const pasteList: Array<menuContentType> = [
    {
      text: "粘贴到节点下方",
      keys: "",
      func: () => {
        fatherItem = treeItem
        if (Tree.canMoveToTreeItems(checkedItems, fatherItem, 'after')) {
          Tree.moveToTreeItems(checkedItems, fatherItem, 'after')
          checkedItems = null
        } else {
          checkedItems = null
        }
      },
    },
    {
      text: "粘贴到节点上方",
      keys: "",
      func: () => {
        fatherItem = treeItem
        if (Tree.canMoveToTreeItems(checkedItems, fatherItem, 'before')) {
          Tree.moveToTreeItems(checkedItems, fatherItem, 'before')
          checkedItems = null
        } else {
          checkedItems = null
        }
      },
    },
    {
      text: "粘贴到节点内部",
      keys: "",
      func: () => {
        fatherItem = treeItem
        if (Tree.canMoveToTreeItems(checkedItems, fatherItem, 'inner')) {
          Tree.moveToTreeItems(checkedItems, fatherItem, 'inner')
          checkedItems = null
        } else {
          checkedItems = null
        }
      },
    },
  ]
  if (checkedItems) {
    pasteList.forEach((item) => {
      baseItems.splice(-8, 0, item)
    })
  }
  const enditingList = {
    text: "编辑",
    keys: "",
    func: () => {
      if (treeItem.sceneObject) {
        if ('positionEditing' in treeItem.sceneObject) {
          treeItem.sceneObject.positionEditing = true
        } else if ('editing' in treeItem.sceneObject) {
          treeItem.sceneObject.editing = true
        }
      }
    },
  }
  if (treeItem.sceneObject) {
    if ('positionEditing' in treeItem.sceneObject || 'editing' in treeItem.sceneObject) {
      baseItems.splice(1, 0, enditingList)
    }
  }
  const Geojson = {
    text: "转为ES点线面对象",
    keys: "",
    func: () => {
      if (treeItem.sceneObject) {
        const sceneObject = treeItem.sceneObject as ESGeoJson
        const uri = sceneObject.uri
        const data = sceneObject.data
        if (!uri && !data) {
          Message.error('此场景对象不存在uri属性或者data属性，请检查')
          return
        }
        let json
        if (uri) {
          getNoToken(uri).then((res: any) => {
            json = res
          }).catch(error => {
            console.log(error);
          })
        } else if (data) {
          json = data
        }
        itemGeoJsonTOESObjects(json)
      }
    },
  }
  if (treeItem.sceneObject) {
    if (treeItem.sceneObject instanceof ESGeoJson) {
      baseItems.splice(2, 0, Geojson)
    }
  }
  const copyUrl = [
    {
      text: "复制服务地址",
      keys: "",
      func: () => {
        if (treeItem.sceneObject) {
          if ('url' in treeItem.sceneObject) {
            const url = treeItem.sceneObject.url as string
            if (url.length > 0) {
              copyClipboard(url)
            } else {
              Message.error('url地址为空');
            }
          }
        }
      },
    },
    {
      text: "加载Cesium代码",
      keys: "",
      func: () => {
        if (treeItem.sceneObject) {
          popTreeItem.value = treeItem.sceneObject

        }
      },
    },
  ]
  // if (treeItem.sceneObject) {
  //   if (treeItem.sceneObject instanceof ESImageryLayer || treeItem.sceneObject instanceof ES3DTileset || treeItem.sceneObject instanceof ESTerrainLayer) {
  //     copyUrl.forEach((item) => {
  //       baseItems.splice(1, 0, item)
  //     })
  //   }
  // }

  menuContent.value = baseItems
}

const copyClipboard = async (text: string) => {//复制
  navigator.clipboard.writeText(text)
    .then(function () {
      Message.success('复制成功');
    }, function (e) {
      Message.error('复制失败');
    });
}

const deleteItem = (e: KeyboardEvent) => {
  if (e.key === 'Delete') {
    if (sceneTree.selectedItems.length === 0) return
    deleteFlag.value = true
    messageBox({ text: '确认删除图层?' })
      .then(() => {
        confirm()
      })
      .catch((err) => {
      })
  }
}

const menuContent = ref<Array<menuContentType>>([])
const contexMenuEvent = (treeItem: SceneTreeItem | undefined) => {//树内右键暴露出来的事件
  if (!treeItem) {
    // 右键空白 啥也不做；
    // whiteSpaceContexMenuEvent()
  } else if (treeItem.type === 'Folder') {
    treeItemContexMenuEvent(treeItem)
  } else {
    // console.log(treeItem, 'treeItem')
    imageContexMenuEvent(treeItem)
  }
}
const flyTo = (treeItem: SceneTreeItem) => {
  const { sceneObject } = treeItem
  if (sceneObject && Reflect.has(sceneObject, 'flyTo')) {
    // @ts-ignore
    sceneObject.flyTo()
  } else {
    Message.warning('暂不支持定位!')
  }
}//拖拽Geojson
const dragEnter = (event: Event) => {
  event.preventDefault();
}
const dragLeave = (event: Event) => {
  event.preventDefault();
}
const dragOver = (event: Event) => {
  event.preventDefault();
}
const dropFile = async (event: Event) => {
  event.preventDefault();
  //@ts-ignore
  let fileList = event.dataTransfer.files
  Object.keys(fileList).forEach(item => {
    // console.log(fileList);
    const reader = new FileReader()
    reader.readAsText(fileList[item], 'utf8')
    reader.onload = () => {
      if (!reader.result) return
      const result = reader.result as string
      const json = JSON.parse(result)
      let geo_data;
      if (json.type === 'Topology') {
        geo_data = topojson.mesh(json)
      } else {
        geo_data = json
      }
      geoJsonTOESObjects(geo_data)
    }
    reader.onerror = () => {
      console.log('onError')
    }
  })
}
const geoJsonTOESObjects = (a: any) => {
  messageBox({
    text: '点击确认转为ES点线面矢量对象，点击取消创建ESFGeojson对象？',
    cancelButtonText: '取消',
    confirmButtonText: '确认',
    title: '提示',
  })
    .then(() => {
      const b = geojsonToPointsLinesPolygons(a)
      if (b.points.length > 0 || b.lines.length > 0 || b.polygons.length > 0) {
        const group = xbsjEarthUi.createGroupTreeItem('Geojson')
        if (b.points.length > 0) {
          const pointsGroup = xbsjEarthUi.createGroupTreeItem('points', undefined, group, 'Inner') as SceneTreeItem
          createpoints(xbsjEarthUi, b.points, pointsGroup)
        }
        if (b.lines.length > 0) {
          const linesGroup = xbsjEarthUi.createGroupTreeItem('lines', undefined, group, 'Inner') as SceneTreeItem
          createLines(xbsjEarthUi, b.lines, linesGroup)
        }
        if (b.polygons.length > 0) {
          const polygonsGroup = xbsjEarthUi.createGroupTreeItem('polygons', undefined, group, 'Inner') as SceneTreeItem
          createpolygons(xbsjEarthUi, b.polygons, polygonsGroup)
        }
      }
    })
    .catch((err) => {
      const currentTreeItem = sceneTree.lastSelectedItem
      let newTreeItem
      if (!currentTreeItem) {
        newTreeItem = sceneTree.createSceneObjectTreeItem('ESGeoJson')
      } else if (currentTreeItem?.type === 'Folder') {
        newTreeItem = sceneTree.createSceneObjectTreeItem('ESGeoJson', undefined, currentTreeItem, 'Inner')
      } else {
        newTreeItem = sceneTree.createSceneObjectTreeItem('ESGeoJson', undefined, currentTreeItem, 'After')
      }
      if (!newTreeItem) return
      sceneTree.uiTree.clearAllSelectedItems()
      newTreeItem.uiTreeObject.selected = true
      if (!newTreeItem.sceneObject) return
      if (newTreeItem.sceneObject.typeName !== 'ESGeoJson') return
      const sceneObject = newTreeItem.sceneObject as ESGeoJson
      xbsjEarthUi.propSceneTree = newTreeItem
      sceneObject.data = a
      console.log(err);
    })

}
const itemGeoJsonTOESObjects = (a: any) => {
  const b = geojsonToPointsLinesPolygons(a)
  if (b.points.length > 0 || b.lines.length > 0 || b.polygons.length > 0) {
    const group = xbsjEarthUi.createGroupTreeItem('Geojson')
    if (b.points.length > 0) {
      const pointsGroup = xbsjEarthUi.createGroupTreeItem('points', undefined, group, 'Inner') as SceneTreeItem
      createpoints(xbsjEarthUi, b.points, pointsGroup)
    }
    if (b.lines.length > 0) {
      const linesGroup = xbsjEarthUi.createGroupTreeItem('lines', undefined, group, 'Inner') as SceneTreeItem
      createLines(xbsjEarthUi, b.lines, linesGroup)
    }
    if (b.polygons.length > 0) {
      const polygonsGroup = xbsjEarthUi.createGroupTreeItem('polygons', undefined, group, 'Inner') as SceneTreeItem
      createpolygons(xbsjEarthUi, b.polygons, polygonsGroup)
    }
  } else {
    Message.warning('请检查geojson格式是否正确')
  }

}
</script>

<style scoped>
.scene-tree-wrapper {
  height: 100%;
}

.scene-tree-comp {
  width: 100%;
  height: calc(100% - 30px);
}
</style>